package ua.yandex.collections;

public class MyArrayList implements MyList {

    private static final int INITIAL_CAPACITY = 10;
    private static final int INCREASING_COEFFICIENT = 2;
    private Object[] array;
    private int size = 0;

    public MyArrayList() {
        array = new Object[INITIAL_CAPACITY];
    }

    public MyArrayList(int initialCapacity) {
        array = new Object[initialCapacity];

    }

    @Override
    public void add(Object e) {
        add(size, e);
    }

    @Override
    public void add(int index, Object e) {
        checkIndexInRangeForAdding(index);
        if (!isEnoughSpace()) {
            ensureCapacity(array.length * INCREASING_COEFFICIENT);
        }
        if (index == size) {
            array[index] = e;
        } else {
            Object[] tempArray = new Object[size - index + 1];
            System.arraycopy(array, index, tempArray, 0, size - index + 1);
            array[index] = e;
            System.arraycopy(tempArray,
                    0,
                    array,
                    index + 1,
                    size - index + 1);
        }
        size++;
    }

    @Override
    public void addAll(Object[] c) {
        addAll(size, c);
    }

    @Override
    public void addAll(int index, Object[] c) {
        for (int i = 0; i < c.length; i++) {
            add(index + i, c[i]);
        }
    }

    @Override
    public Object get(int index) {
        checkIndexInRange(index);
        return array[index];
    }

    @Override
    public Object remove(int index) {
        checkIndexInRange(index);
        Object element = array[index];
        int lengthOfArrayPart = size - index;
        Object[] tempArray = new Object[lengthOfArrayPart];
        System.arraycopy(array, index + 1, tempArray, 0, lengthOfArrayPart);
        System.arraycopy(tempArray, 0, array, index, lengthOfArrayPart);
        array[size - 1] = null;
        size--;
        return element;
    }

    @Override
    public void set(int index, Object e) {
        checkIndexInRange(index);
        array[index] = e;
    }

    @Override
    public int indexOf(Object o) {
        int index = 0;
        while (!o.equals(array[index]) && index < size) {
            index++;
        }
        if (index == size) {
            index = -1;
        }
        return index;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public void clear() {
        Object[] tempArray = new Object[array.length];
        array = tempArray;
        size = 0;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public Object[] toArray() {
        Object[] resultArray = new Object[size];
        System.arraycopy(array, 0, resultArray, 0, size);
        return resultArray;
    }

    @Override
    public String toString() {
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < size; i++) {
            buf.append(array[i].toString());
            if (i < size - 1) {
                buf.append(", ");
            }
        }
        return buf.toString();
    }

    public void ensureCapacity(int minCapacity) {
        if (minCapacity > array.length) {
            Object[] tempArray = new Object[minCapacity];
            System.arraycopy(array, 0, tempArray, 0, array.length);
            array = tempArray;
        }
    }

    private void checkIndexInRange(int index) {
        if (index >= size || index < 0) {
            throw new IllegalIndexException();
        }
    }

    private void checkIndexInRangeForAdding(int index) {
        if (index > size || index < 0) {
            throw new IllegalIndexException();
        }
    }

    private boolean isEnoughSpace() {
        return array.length > size;
    }

    int getCapacity() {
        return array.length;
    }
}
